#include "testApp.h"
#include <iostream>
#include <fstream>
#include "stdio.h"

bool ofFileExists(string filename) {
   ifstream inp;
   inp.open(filename.c_str(), ifstream::in);
   inp.close();
   return !inp.fail();
}

vector<string> ofReadLines(string filename) {
    vector<string> lines;
    filename = ofToDataPath(filename);
    if (!ofFileExists(filename)) {cout << "ofReadLines: File not found: " << filename << endl; return lines;}
    ifstream f(filename.c_str(),ios::in);
    string line;
    while (getline(f,line)) lines.push_back(line);
    f.close();
    return lines;
}

//--------------------------------------------------------------
void testApp::setup(){
    //placement tester
    back.loadImage("kaaas.jpg");

    //screensaver items
    example.loadMovie("movies/designforpace_screensaver.mov");
    movie = false;

    //sound int
    ammountRecog = 2;
    ammountAnim = 3;


    //sound loaders
    for (int i=0;i<ammountRecog;i++) {
        Recognition[i].loadSound("sounds/recognition_" + ofToString(i+1) + ".mp3");
    }
    for (int i=0;i<ammountAnim;i++) {
        Animation[i].loadSound("sounds/animation_" + ofToString(i+1) + ".mp3");
    }

    //standard variables
    tagTimer = 0;
    tagLine = "";
    ofHideCursor();
    backTint = 0;
    request = "";
    ofBackground(0,0,0);

    //variables for the different durations
    startDuration = 10000;      //15 seconds
    mainDuration = 50000;       //75 seconds
    sSaverHolder = 10000;       //15 seconds
    sSaverDuration = 2000;      //3 seconds
    delay = 500;
    bouncing = true;

    //imageholder
    iArray =  ofReadLines("lib/images.txt");
    for (int i=0;i<iArray.size();i++) {
        Pics[i].loadImage("images/" + iArray[i] + ".jpg");
    }
    ofEnableAlphaBlending();
    stage = 0;

    //deceleration
    if (bouncing == true) {
        dv = 0.02;
    } else {
        dv = 0.0001;
    }
}

//--------------------------------------------------------------
void testApp::update(){
    //when the screensaver is requested, it is printed upon the screen
    if (movie == true) {
        //idling is required to get a new frame each time
        example.idleMovie();
        //ends the movie
        if (timer == sSaverDuration) {
        //if (example.getCurrentFrame() == example.getTotalNumFrames()) {
            cout << "screensaver off" << endl;
            movie = false;
            timer = 0;
        }
    }

    //if the screen is blank, stage = 0
    tagTimer++;
    //every .5 seconds the tag is resetted, so new books can always be placed
    if (tagTimer >= 1000) {
        tagLine = "";
        tagTimer = 0;
        cout << "newcommand" << endl;
    }
    //for loop for calculations, everything within this for loop is calculated for each ball
    for(int i=0;i<ballen.size();i++)
    {
        //during stage 1, the words are placed on the screen, searching for their starting position
        if (stage == 1) {
            ballen[i].startX += (ballen[i].xBal-ballen[i].startX)/delay*3;
            ballen[i].startY += (ballen[i].yBal-ballen[i].startY)/delay*3;
            timer++;
            //waits for a short pause and starts the animation
            if (timer == 1000) {
                Animation[int(ofRandom(0,ammountAnim-1))].play();
            }
            //automatically after 5 seconds, the scene proceedes to stage 2
            if (timer >= startDuration) {
                stage = 2;
                timer = 0;
            }
            //this was the original code, but recently stopped working :(
            /*if (ballen[i].startX - ballen[i].xBal < 1 && ballen[i].startX - ballen[i].xBal > -1) {
                stage = 2;
            }*/
        }
        //in stage 2, all words are floating through the screen
        else if (stage == 2) {
            if (bouncing == true) {
                for (int j=0;j<ballen.size();j++) {
                    if (i != j) {
                        distX = ballen[i].xBal - ballen[j].xBal;
                        distY = ballen[i].yBal - ballen[j].yBal;
                        dist = sqrt((distY*distY)+(distX+distX));

                        //when the words are getting near eachother, they will push eachother away
                        if (dist <= ballen[i].width+ballen[j].width*10/ballen.size() && dist >= 50) {
                            if (distX > 0) {
                                ballen[i].vxBal += (.3/distX);
                                ballen[j].vxBal -= (.3/distX);
                            }
                            if (distY > 0) {
                                ballen[i].vyBal += (.3/distY);
                                ballen[j].vyBal -= (.3/distY);
                            }
                        }
                    }
                }
                //easy way to make things move slower on the screen
                ballen[i].yBal += ballen[i].vyBal/delay;
                ballen[i].xBal += ballen[i].vxBal/delay;
            } else {
                ballen[i].yBal += ballen[i].vyBal/20;
                ballen[i].xBal += ballen[i].vxBal/20;
            }

            //the words are pushed away from against the walls
            if (ballen[i].yBal > 850-ballen[i].width) {
                if (bouncing == true) {
                    ballen[i].vyBal /= 1 + dv;
                }
                ballen[i].vyBal -= dv;
            }
            if (ballen[i].xBal > 450-ballen[i].height) {
                if (bouncing == true) {
                    ballen[i].vxBal /= 1 + dv;
                }
                ballen[i].vxBal -= dv;
            }
            if (ballen[i].yBal < 150+ballen[i].width) {
                if (bouncing == true) {
                    ballen[i].vyBal /= 1 + dv;
                }
                ballen[i].vyBal += dv;
            }
            if (ballen[i].xBal < 150+ballen[i].height) {
                if (bouncing == true) {
                    ballen[i].vxBal /= 1 + dv;
                }
                ballen[i].vxBal += dv;
            }
        }
        //at stage 3, all words are thrown out of the screen to end the scene
        else if (stage == 3) {
            ballen[i].vxBal *= 1.01;
            ballen[i].vyBal *= 1.01;

            ballen[i].yBal += ballen[i].vyBal/delay;
            ballen[i].xBal += ballen[i].vxBal/delay;

            //and after a few seconds, the scene returns to stage 0
        }
    }
    if (stage == 2) {
        //after 1 minute and 15 seconds, the scene automatically proceedes to stage 3
        timer++;
        if (timer >= mainDuration) {
            stage = 3;
            timer = 0;
        }
    }

    //calls for the screensaver if nothing happens for a period of time
    if (stage == 3 || stage == 0) {
        timer++;
        if (timer >= sSaverHolder) {
            timer = 0;
            screenSaver();
        }
    }
}


//--------------------------------------------------------------
void testApp::draw(){
    //the var backTint ensures a simple fade in for the requested background
    ofSetColor(backTint,backTint,backTint);
    if (backTint <= 255 && stage == 1) {
        backTint += 2;
    } else if (backTint >= 0 && stage == 3) {
        backTint--;
    }
    //for tester
    //ofSetColor(255,255,255);

    back.draw(0,0);
    if (backTint <= 255) {
        ofSetColor(255,255,255,255-backTint);
        ofRect(0,0,1050,650);
    }

    if (movie == true) {
        ofSetColor(0xFFFFFF);
        example.draw(0,0);
    }

    //places two black windows, which are required to position the screen (we used a 2:1 aspect ratio)
    ofSetColor(0x000000);
    ofRect(0,0,1050,10);
    ofRect(0,635,1050,300);

    //loop to draw each class
    for(int i=0;i<ballen.size();i++)
    {
        ofPushMatrix();
            //during stage 1 the balls are placed upon a different x and y position
            if (stage == 1) {
                ofTranslate(ballen[i].startY,ballen[i].startX);
            }
            else if (stage == 2 || stage == 3) {
                ofTranslate(ballen[i].yBal, ballen[i].xBal);
            }
            //the IMG variable defines weither an image is available with thesame name as the word
            if (ballen[i].IMG == -1) {
                //weither the word is informative or not, changes the textcolor
                if (rArray[i] == "inf") {
                    ofSetColor(0xCEEEFF);
                } else {
                    ofSetColor(0xA9FF9B);
                }
                verdana[i].drawString(sArray[i],ballen[i].width/8,ballen[i].height/1.6);
            //when an IMG is found, draw the image instead
            } else {
                ofSetColor(0xFFFFFF);
                Pics[ballen[i].IMG].draw(0,0,ballen[i].weight*3,ballen[i].weight*3);
            }
        //ending the matrix, so the next class can be drawn
        ofPopMatrix();
    }
}

//the function when an existing book is scanned
void testApp::newBook(string request) {
    //put all the strings into one base array
    totalArray = ofReadLines("lib/" + request + ".txt");

    //clears all used arrays to work with
    sArray.clear();
    pArray.clear();
    rArray.clear();

    //this loop places the right strings into the right array
    //(s = strings, p = priority, r = relation)
    for (int i=0;i<totalArray.size();i++) {
        if (i % 4 == 0) {
            sArray.push_back(totalArray[i]);
        }
        if (i % 4 == 1) {
            pArray.push_back(totalArray[i]);
        }
        if (i % 4 == 2) {
            rArray.push_back(totalArray[i]);
        }
        cout << totalArray[i] << endl;
    }

    //when the book is found, the next stage is called
    stage = 1;

    //the timer used several times has to be resetted every time a new stage is called
    timer = 0;

    //creates as many balls/words as the array contains
    ballen.assign(sArray.size()-1,ball);

    //loads the background using the first word fromout the array
    back.loadImage("backgrounds/" + sArray[0] + ".jpg");

    //the main to create a set of *balls* which are used as background to calculate the movement and bouncing
    for(int i=0;i<ballen.size()-1;i++)
    {
        //there are 4 different priorities, using different text sizes
        if (pArray[i] == "normal") {
            ballen[i].weight = 24;
        }
        else if (pArray[i] == "high") {
            ballen[i].weight = 32;
        }
        else if (pArray[i] == "max") {
            ballen[i].weight = 48;
        }
        else {
            ballen[i].weight = 16;
        }

        //basic starting values
        ballen[i].height = ballen[i].weight * 2;
        ballen[i].width = ((sArray[i].length()+3) * ballen[i].weight * .8) + 10;
        ballen[i].yBal=ofRandom(50,850);
        ballen[i].xBal=ofRandom(50,350);
        ballen[i].startY = 400;
        ballen[i].startX = 500;
        ballen[i].vyBal = ofRandom(dv*10,dv*50);
        ballen[i].vxBal = ofRandom(dv*10,dv*50);
        timer = 0;
        //weither the word is informative or not, the right font is used, which is located in the .txt file
        if (rArray[i] == "inf") {
            verdana[i].loadFont(sArray[sArray.size()-1],ballen[i].weight, true, true);
        } else {
            verdana[i].loadFont(sArray[sArray.size()-2],ballen[i].weight, true, true);
        }

        //the IMG value starts with -1
        ballen[i].IMG = -1;

        //if an image is found, the value is replaced with the correct value within the array
        for (int j=0;j<iArray.size();j++) {
            if (iArray[j] == sArray[i]) {
                ballen[i].IMG = j;
            }
        }
    }
}


//--------------------------------------------------------------
void testApp::keyPressed  (int key){
    //whenever a new key is pressed, the timer is resetted and the next key is inserted
    tagTimer = 0;
    tagLine.append(1, (char)key );

    //when the tag contains 10 characters, it tries to find a book
    if (tagLine.length() == 10) {
        if (tagLine != request) {
            //only when the file actually exists, a new book is *produced*
            if (ofFileExists(ofToDataPath("lib/" + tagLine + ".txt"))) {
                request = tagLine;
                newBook(request);
                movie = false;
                //plays a random feedback sound
                Recognition[int(ofRandom(0,ammountRecog-1))].play();
                timer = 0;
            }
            //and after each script, the tag has to be resetted
            tagLine = "";
        }
    }
}

//starts the screensaver
void testApp::screenSaver () {
    cout << "screenSaver on" << endl;
    movie = true;
    example.play();
}
